
#include "jsnet_dlk.h"
#include "dlk_frame.h"
#include "dlk_send_receive.h"
#include "dlk_cmd.h"
#include "dlk_parameter.h"
#include "dlk_encrypt.h"
#include "dlk_debug_print.h"

/*********************************
the dlk_cmd is the definition of communication between tow DLK layers
it's depended dlk_frame, dlk_parameter, dlk_encrypt, dlk_send_receive
*********************************/

static FRAME_STRUCT send_frame_struct;
static uint8_t send_frame_payload_buffer[FRAME_PAYLOAD_MAX_LEN+1];
static uint8_t send_target_node_addr[FRAME_LONG_ADDR_LEN];
static uint8_t send_source_node_addr[FRAME_LONG_ADDR_LEN];
static uint8_t dlk_send_cmd_buffer[FRAME_LEN_MAX];
static uint8_t dlk_send_cmd_buffer_len;

/**
if(framing(send_frame_struct,
send_frame_payload_buffer,
send_target_node_addr,
send_source_node_addr,
dlk_send_cmd_buffer, &dlk_send_cmd_buffer_len);
**/

uint8_t dlk_cmd_open_node_request(void)
{
	send_frame_struct.head_byte.encrypted = FRAME_UNENCRYPTED;
	send_frame_struct.head_byte.need_ack = FRAME_NO_ACK;
	send_frame_struct.head_byte.target_addr_type = FRAME_SHORT_ADDR;
	send_frame_struct.head_byte.source_addr_type = FRAME_LONG_ADDR;
	send_frame_struct.head_byte.frame_type = FRAME_CMD_OPEN_NODE_REQUEST;
	send_frame_struct.frame_count = frame_count_get();

	send_frame_struct.playload_len = 0;

	if(framing(&send_frame_struct,
		send_frame_payload_buffer,
		broadcast_addr_get(),
		local_node_addr_get(send_frame_struct.head_byte.source_addr_type),
		dlk_send_cmd_buffer, &dlk_send_cmd_buffer_len) == 0){
		return 0;
	}

	if(dlk_send(dlk_send_cmd_buffer, dlk_send_cmd_buffer_len, 0, 0, 0) == 0){
		return 0;
	}
	return 1;
}

#if(JSNET_DLK_DEVICE_TYPE == JSNET_DLK_DEVICE_TYPE_STD_NODE)
uint8_t dlk_cmd_open_node_response(uint8_t* target_node_addr, uint8_t target_node_addr_type)
{
	if(target_node_addr_type != FRAME_LONG_ADDR){
		return 0;
	}
	send_frame_struct.head_byte.encrypted = FRAME_UNENCRYPTED;
	send_frame_struct.head_byte.need_ack = FRAME_NO_ACK;
	send_frame_struct.head_byte.target_addr_type = target_node_addr_type;
	send_frame_struct.head_byte.source_addr_type = FRAME_LONG_ADDR;
	send_frame_struct.head_byte.frame_type = FRAME_CMD_OPEN_NODE_RESPONSE;
	send_frame_struct.frame_count = frame_count_get();

	send_frame_struct.playload_len = 0;

	if(framing(&send_frame_struct,
		send_frame_payload_buffer,
		target_node_addr,
		local_node_addr_get(send_frame_struct.head_byte.source_addr_type),
		dlk_send_cmd_buffer, &dlk_send_cmd_buffer_len) == 0){
		return 0;
	}

	if(dlk_send(dlk_send_cmd_buffer, dlk_send_cmd_buffer_len, 1, 0, 0) == 0){
		return 0;
	}
	return 1;
}
#endif

uint8_t dlk_cmd_link_request(uint8_t* target_node_addr, uint8_t target_node_addr_type)
{
	if(target_node_addr_type != FRAME_LONG_ADDR){
		return 0;
	}

	send_frame_struct.head_byte.encrypted = FRAME_UNENCRYPTED;
	send_frame_struct.head_byte.need_ack = FRAME_NO_ACK;
	send_frame_struct.head_byte.target_addr_type = target_node_addr_type;
	send_frame_struct.head_byte.source_addr_type = FRAME_LONG_ADDR;
	send_frame_struct.head_byte.frame_type = FRAME_CMD_LINK_REQUEST;
	send_frame_struct.frame_count = frame_count_get();

	send_frame_struct.playload_len = 0;

	if(framing(&send_frame_struct,
		send_frame_payload_buffer,
		target_node_addr,
		local_node_addr_get(send_frame_struct.head_byte.source_addr_type),
		dlk_send_cmd_buffer, &dlk_send_cmd_buffer_len) == 0){
		return 0;
	}

	if(dlk_send(dlk_send_cmd_buffer, dlk_send_cmd_buffer_len, 0, 0, 0) == 0){
		return 0;
	}
	return 1;
}

#if(JSNET_DLK_DEVICE_TYPE == JSNET_DLK_DEVICE_TYPE_STD_NODE)
uint8_t  dlk_cmd_link_response(uint8_t* target_node_addr, uint8_t target_node_addr_type,
							uint8_t key)
{
	if(target_node_addr_type != FRAME_LONG_ADDR){
		return 0;
	}

	send_frame_struct.head_byte.encrypted = FRAME_UNENCRYPTED;
	send_frame_struct.head_byte.need_ack = FRAME_NO_ACK;
	send_frame_struct.head_byte.target_addr_type = target_node_addr_type;
	send_frame_struct.head_byte.source_addr_type = FRAME_LONG_ADDR;
	send_frame_struct.head_byte.frame_type = FRAME_CMD_LINK_RESPONSE;
	send_frame_struct.frame_count = frame_count_get();

	send_frame_payload_buffer[0] = key;
	send_frame_struct.playload_len = 1;

	if(framing(&send_frame_struct,
		send_frame_payload_buffer,
		target_node_addr,
		local_node_addr_get(send_frame_struct.head_byte.source_addr_type),
		dlk_send_cmd_buffer, &dlk_send_cmd_buffer_len) == 0){
		return 0;
	}

	if(dlk_send(dlk_send_cmd_buffer, dlk_send_cmd_buffer_len ,1 ,0, 0) == 0){
		return 0;
	}
	return 1;
}
#endif

uint8_t dlk_cmd_device_notify(uint8_t* target_node_addr, uint8_t target_node_addr_type,
							uint8_t* short_local_node_addr, uint8_t local_device_type)
{
	if(target_node_addr_type != FRAME_LONG_ADDR){
		return 0;
	}

	send_frame_struct.head_byte.encrypted = FRAME_ENCRYPTED;
	send_frame_struct.head_byte.need_ack = FRAME_NO_ACK;
	send_frame_struct.head_byte.target_addr_type = target_node_addr_type;
	send_frame_struct.head_byte.source_addr_type = FRAME_LONG_ADDR;
	send_frame_struct.head_byte.frame_type = FRAME_CMD_DEVICE_NOTIFY;
	send_frame_struct.frame_count = frame_count_get();

	send_frame_payload_buffer[0] = short_local_node_addr[0];
	send_frame_payload_buffer[1] = local_device_type;
	send_frame_struct.playload_len = 2;

	if(framing(&send_frame_struct,
		send_frame_payload_buffer,
		target_node_addr,
		local_node_addr_get(send_frame_struct.head_byte.source_addr_type),
		dlk_send_cmd_buffer, &dlk_send_cmd_buffer_len) == 0){
		return 0;
	}
	encrypt(dlk_send_cmd_buffer, &dlk_send_cmd_buffer_len);

	if(dlk_send(dlk_send_cmd_buffer, dlk_send_cmd_buffer_len, 1, 0, 0) == 0){
		return 0;
	}
	return 1;
}

uint8_t dlk_cmd_unlink_notify(void)
{
	send_frame_struct.head_byte.encrypted = FRAME_ENCRYPTED;
	send_frame_struct.head_byte.need_ack = FRAME_NO_ACK;
	send_frame_struct.head_byte.target_addr_type = FRAME_SHORT_ADDR;
	send_frame_struct.head_byte.source_addr_type = FRAME_LONG_ADDR;
	send_frame_struct.head_byte.frame_type = FRAME_CMD_UNLINK_NOTIFY;
	send_frame_struct.frame_count = frame_count_get();

	send_frame_struct.playload_len = 0;

	if(framing(&send_frame_struct,
		send_frame_payload_buffer,
		broadcast_addr_get(),
		local_node_addr_get(send_frame_struct.head_byte.source_addr_type),
		dlk_send_cmd_buffer, &dlk_send_cmd_buffer_len) == 0){
		return 0;
	}
	encrypt(dlk_send_cmd_buffer, &dlk_send_cmd_buffer_len);
	
	if(dlk_send(dlk_send_cmd_buffer, dlk_send_cmd_buffer_len, 0, 0, 0) == 0){
		return 0;
	}
	return 1;
}

static void set_send_source_node_addr_type(void)
{
	if(broadcast_addr_check(local_node_addr_get(FRAME_SHORT_ADDR), FRAME_SHORT_ADDR)
		== 0){
		send_frame_struct.head_byte.source_addr_type = FRAME_SHORT_ADDR;
	}
	else{
		send_frame_struct.head_byte.source_addr_type = FRAME_LONG_ADDR;
	}
}

uint8_t dlk_cmd_data_request(uint8_t* target_node_addr, uint8_t target_node_addr_type)
{
	send_frame_struct.head_byte.encrypted = FRAME_ENCRYPTED;
	send_frame_struct.head_byte.need_ack = FRAME_NEED_ACK;
	send_frame_struct.head_byte.target_addr_type = target_node_addr_type;
	set_send_source_node_addr_type();
	send_frame_struct.head_byte.frame_type = FRAME_CMD_DATA_REQUEST;

	send_frame_struct.frame_count = frame_count_get();

	send_frame_struct.playload_len = 0;

	if(framing(&send_frame_struct,
		send_frame_payload_buffer,
		target_node_addr,
		local_node_addr_get(send_frame_struct.head_byte.source_addr_type),
		dlk_send_cmd_buffer, &dlk_send_cmd_buffer_len) == 0){
		return 0;
	}
	encrypt(dlk_send_cmd_buffer, &dlk_send_cmd_buffer_len);
	
	if(dlk_send(dlk_send_cmd_buffer, dlk_send_cmd_buffer_len, 1, 1, 1) == 0){
		return 0;
	}
	return 1;
}

uint8_t dlk_cmd_ack(uint8_t* target_node_addr, uint8_t target_node_addr_type,
					uint8_t rec_frame_count)
{
	send_frame_struct.head_byte.encrypted = FRAME_UNENCRYPTED;
	send_frame_struct.head_byte.need_ack = FRAME_NO_ACK;
	send_frame_struct.head_byte.target_addr_type = target_node_addr_type;
	set_send_source_node_addr_type();
	send_frame_struct.head_byte.frame_type = FRAME_CMD_ACK;

	send_frame_struct.frame_count = frame_count_get();

	send_frame_payload_buffer[0] = rec_frame_count;
	send_frame_struct.playload_len = 1;

	if(framing(&send_frame_struct,
		send_frame_payload_buffer,
		target_node_addr,
		local_node_addr_get(send_frame_struct.head_byte.source_addr_type),
		dlk_send_cmd_buffer, &dlk_send_cmd_buffer_len) == 0){
		return 0;
	}
	
	if(dlk_send(dlk_send_cmd_buffer, dlk_send_cmd_buffer_len, 1, 0, 0) == 0){
		return 0;
	}
	
	dlk_debug_print_str("dlk_cmd_ack\r\n");
	
	return 1;
}

uint8_t dlk_data_send(uint8_t* target_node_addr, uint8_t target_node_addr_type,
					uint8_t* send_data, uint8_t send_data_len)
{
	send_frame_struct.head_byte.encrypted = FRAME_ENCRYPTED;
	send_frame_struct.head_byte.need_ack = FRAME_NEED_ACK;
	send_frame_struct.head_byte.target_addr_type = target_node_addr_type;
	set_send_source_node_addr_type();
	send_frame_struct.head_byte.frame_type = FRAME_DATA;

	send_frame_struct.frame_count = frame_count_get();

	send_frame_struct.playload_len = send_data_len;
	
	if(framing(&send_frame_struct,
		send_data,
		target_node_addr,
		local_node_addr_get(send_frame_struct.head_byte.source_addr_type),
		dlk_send_cmd_buffer, &dlk_send_cmd_buffer_len) == 0){
		return 0;
	}
	encrypt(dlk_send_cmd_buffer, &dlk_send_cmd_buffer_len);
	
	if(dlk_send(dlk_send_cmd_buffer, dlk_send_cmd_buffer_len, 1, 1, 1) == 0){
		return 0;
	}
	return 1;
}
